from  deslab import *

"""
This is the script for the computation of minimal event bases that ensure diagnosability.
The algorithms are part of the paper:
Basilio, J., Lima, S., Lafortune, S.,, e Moreira, M. (2012), "Computation of minimal
event bases that ensure diagnosability," Discrete Event Dynamic Systems, 
"""

from minimal_basis import *
from algorithm3 import find_Sigma_IES_Obs
set = frozenset

        
def find_Sigma_IES_Uobs(XST, S_Y, S_N, So, Sop): 
    """This function calculates the  event set Sigma_ies^0
    for observable cycles according to algorithm 4 of paper    
    """     
    # Step 1: 
    #   We calculate is $S_{Y}^h$ and $P_{oo\prime}(S_Y^h)$ 
    Sh_Y = set([i.s for i in S_Y if all(e in So-Sop for e in i.cycle)]) 
    Poop_Sh_Y = [proj(sy,Sop) for sy in Sh_Y] 
    
    # Step 2:
    #   We calculate is $S_{NN}$  and  $S^{NN}_{YY}$ 
    SNN = set([i.s for i in  XST if YN_type(i.xp_d) =='N' and YN_type(i.x_d) =='N'])    
    SYN_YY = set([i.s_max for i in XST if YN_type(i.xp_d) =='Y' and YN_type(i.x_d) =='Y'] )     
    # loop for every $s\prime_i$   
    Sigma_ies_i = set()           
    for sp_i in Poop_Sh_Y :
        Sh_Y_i = set([sy for sy in Sh_Y if proj(sy,Sop)==sp_i])  # $S^h_{Y,i}$   
        S_Y_sp = Sh_Y - Sh_Y_i   # this is $S_Y(s_i\prime)$          
        SYN_Y_sp = set([i.s_max for i in XST if i.s in S_Y_sp])  # $S_Y^{YN}$         
        Sh_N_sp =SYN_Y_sp | SYN_YY | S_N | SNN  # $S^h_N(s\prime_i)$          
        # Step 3:
        #   form the set $Sh_{N,i}$
        Sh_N_i = set([sn for sn in Sh_N_sp if sp_i in prefixes(sn) and sn[-1] in Sop])              
        # Step 4:
        #   form the sets $\Sigma^k_{Y,i}$ and $\Sigma^l_{N,i}$   
        SigmaY_i = set([set([e for e in sy if e in So-Sop])  for sy in Sh_Y_i if any(k in So-Sop for k in sy)])     
        SigmaN_i = set([set([e for e in sn if e in So-Sop])  for sn in Sh_N_i if any(k in So-Sop for k in sn)])  
                     
        # Step 5:
        #   form the sets $\Sigma^h_{ies, Yi}$, $\Sigma^h_{ies, Yi}$
        #   and set the right stratification
        Sigma_iesY_i = stratify_sigma(SigmaY_i)
        Sigma_iesN_i = stratify_sigma(SigmaN_i)
        # Compute $\Sigma^h_{ies}$ by taking the union of the former sets               
        Sigma_ies_i |=  set([ Sigma_iesY_i | Sigma_iesN_i])
    # Step 6: 
    #    calculating  $\Sigma^o_{ies}$ as the product of
    #    the collection if $\Sigma^o_{ies,i} \neq \emptyset$     
    if Sigma_ies_i:
        # Step 6:
        #    calculating  $\Sigma^o_{ies}$ as the product of
        #    the collection if $\Sigma^o_{ies,i} \neq \emptyset$   
        Sigma_ies = prodcollection(Sigma_ies_i) 
    else:
        # otherwise $\Sigma^o_{ies}=\{\emptyset\}$
        Sigma_ies = set([set()])    
    # Step 7: 
    #   find the minimals of the poset
    Sigma_ies = minimals_of_poset(Sigma_ies)
    return Sigma_ies


""" TESTING CODE"""

"""
a,c,sf = syms('a c f')
G=load('G_example3')
Gd = load('Gd_example3')
Sop=set([a,c])
Gdprime = diagnoser(G,sf,Sop)
So = Gd.Sigma # set Sigma_o
Gtest = Gdprime//Gd 
I = find_indeterminate_states(G, Gdprime, sf)    
XDS, tree_1 = find_XDS(Gdprime)
XST, tree_2 = prime_paths_cycle_smax(Gtest)  
Sigma_ies, S_Y, S_N = find_Sigma_IES_Obs(XDS, XST, I, So, Sop)
Sigmah_ies = find_Sigma_IES_Uobs(XST, S_Y, S_N, So, Sop)
"""





